#include "Thread.h"
#include "CurrentThread.h"

#include <semaphore.h>

std::atomic_int Thread::numCreated_(0);  // 记录线程个数

Thread::Thread(ThreadFunc func, const std::string& name)
    : started_(false)
    , joined_(false)
    , tid_(0)
    , func_(std::move(func))
    , name_(name)
{
    setDefaultName();
}

Thread::~Thread()
{
    if(started_ && !joined_)  // 线程运行起来，才需要回收相关的资源
    {
        thread_->detach();  // thread类提供了设置分离线程的方法
    }
}

void Thread::start()  // 一个Thread对象记录的就是一个新线程的详细信息
{
    started_ = true;
    sem_t sem;
    sem_init(&sem, false, 0);

    // 开启线程
    thread_ = std::shared_ptr<std::thread>(new std::thread([&](){
        // new了一个线程对象，传线程函数
        // [&]引用方式捕获外部的Thread对象，就能在新的线程中访问Thread对象的成员变量了
        
        // 获取线程的tid
        tid_ = CurrentThread::tid();
        sem_post(&sem);
        // 开启一个新线程，专门执行该线程函数
        func_();  
    }));

    // 这里必须等待获取上面新创建线程的tid值
    sem_wait(&sem);  // 上面新线程tid_ = CurrentThread::tid();如果还没执行完，就会阻塞在这里
}

void Thread::join()
{
    joined_ = true;
    thread_->join();
}

void Thread::setDefaultName()
{
    int num = ++numCreated_;
    if(name_.empty())
    {
    // 如果没有手动给线程设置名字，根据线程的创建的序号，给线程设置一个默认的名字
        char buf[32] = {0};
        snprintf(buf, sizeof buf, "Thread%d", num);
        name_ = buf;
    }
}